//------------------------------------------------------------------------------ 
//  <copyright file="ImageEllipse.h" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//  </copyright>
//------------------------------------------------------------------------------
#pragma once
#include <vt_edgedetect.h>
#include <vt_linedetector.h>
#include "IShape2D.h"


using namespace System;
using namespace System::Collections::Generic;

namespace Microsoft 
{
    namespace Robotics 
    {
        namespace Vision 
        {
			/// <summary>
			/// Managed version of the ellipse returned by VisionTools
			/// </summary>
			public ref struct ImageEllipse : IShape2D
            {
				/// <summary> Gets or sets X coordinate of ellipse center </summary>
				virtual property double CenterX;

				/// <summary> Gets or sets Y coordinate of ellipse center </summary>
				virtual  property double CenterY;

				/// <summary>
				/// Gets a 1 dimensional size of ellipse. Since size is expected to be a one dimensional quantity indicative of size
				/// we use the geometric average of Major and Minor axis half lengths
				/// </summary>
				virtual property double Size1D
				{
					double get()
					{
						return Math::Sqrt(this->MajorAxisLength * this->MinorAxisLength) / 2.0;
					}
				}

				/// <summary> Gets ellipse confidence </summary>
				virtual property double Confidence { double get() { return this->Strength;} }

				/// <summary> Length of "x" (major) axis </summary>
				double MajorAxisLength;

				/// <summary> Length of "y" (minor) axis </summary>
				double MinorAxisLength;

				/// <summary> EllipseSegment tilt angle in radians </summary>
				double Theta;

				/// <summary> Minimum arc-length (angle) parameter value </summary>
				double MinArcLengthAngle;
                    
                /// <summary> Maximum arc-length (angle) parameter value </summary>
                double MaxArcLengthAngle;
                    
                /// <summary> Average strength of edgels (local gradient magnitudes) </summary>
                double Strength;
                    
                /// <summary> Average distance between successive edgels </summary>
                double EdgeDensity;
                    
                /// <summary> Heuristic score for "goodness" of ellipse fit (length * strength / density) </summary>
                double FitScore;

                /// <summary> List of constituent points </summary>
                List<int>^ Points;

                /// <summary> Construct from a native version </summary> 
                ImageEllipse(vt::EllipseSegment *pEllipse)
                {
                    this->CenterX = pEllipse->cx;
                    this->CenterY = pEllipse->cy;
                    this->MajorAxisLength = pEllipse->ax;
                    this->MinorAxisLength = pEllipse->ay;
                    this->Theta = pEllipse->theta;
                    this->MinArcLengthAngle = pEllipse->min_t;
                    this->MaxArcLengthAngle = pEllipse->max_t;
                    this->Strength = pEllipse->strength;
                    this->EdgeDensity = pEllipse->density;
                    this->FitScore = pEllipse->score;

                    this->Points = gcnew List<int>;
                    for (int i = 0 ; i < (int)pEllipse->points.size() ; ++i)
                    {
                        this->Points->Add(pEllipse->points[i]);
                    }
                }
            };
        }
    }
}
